package io.sundial.executor.impl;

import io.sundial.coordination.CoordinatorException;
import io.sundial.coordination.node.Node;
import io.sundial.coordination.tree.Tree;
import io.sundial.coordination.tree.TreeEvent;
import io.sundial.coordination.tree.TreeWatcher;
import io.sundial.engine.exception.StartingException;
import io.sundial.job.JobCommand;

/**
 * 抽象的作业自发式执行器
 *
 * @author Payne 646742615@qq.com
 * 2018/12/20 21:45
 */
public abstract class ListeningExecutor extends InvokingExecutor {
    protected static final String COMMANDS_ROOT = SPRT + "commands";

    private final TreeWatcher commandTreeWatcher = new CommandTreeWatcher();

    @Override
    protected void starting() throws StartingException {
        super.starting();

        // region 监听命令节点树
        try {
            coordinator.watch(COMMANDS_ROOT + SPRT + name, commandTreeWatcher);
        } catch (CoordinatorException e) {
            throw new StartingException(e);
        }
        // endregion
    }

    private class CommandTreeWatcher implements TreeWatcher {

        @Override
        public void onWatched(TreeEvent event) throws Exception {
            Tree tree = event.getTree();
            String root = tree.getRoot();
            TreeEvent.Type type = event.getType();
            switch (type) {
                case NODE_CREATED: {
                    Node node = event.getNode();
                    String path = node.getPath();
                    if (root.equals(path)) return;
                    String name = path.substring((root + SPRT).length());
                    if (name.split(SPRT).length != 4) return;

                    byte[] data = node.getData();
                    JobCommand jobCommand = unmarshal(data, JobCommand.class);
                    // 执行命令
                    execute(jobCommand);
                }
                break;
                case NODE_UPDATED:
                    break;
                case NODE_REMOVED:
                    break;
                case CONN_SUSPENDED:
                    break;
                case CONN_RECONNECTED:
                    break;
                case CONN_LOST:
                    break;
                case TREE_INITIALIZED:
                    break;
            }
        }
    }
}
